var $ = layui.jquery;
$(function () {
    class connectWebSocket extends EventTarget {
        state = 'not-connected';//状态

        constructor(wsUri) {
            super();
            this.wsUri = wsUri;
        }

        connected() {
            if (this.state === 'connected') return false;//当前是已连接状态将不能打开新的ws实例
            // 打开一个 web socket
            this.ws = new WebSocket(this.wsUri);
            //绑定事件
            this.ws.addEventListener('open', event => this.dispatchEvent(new connectWebSocket.MyEvent(event)));
            this.ws.addEventListener('close', event => this.dispatchEvent(new connectWebSocket.MyEvent(event)));
            this.ws.addEventListener('message', event => this.dispatchEvent(new connectWebSocket.MyEvent(event)));
            this.addEventListener('open', () => this.state = 'connected');
            this.addEventListener('close', () => this.state = 'disconnected');
            //返回一个promise
            return new Promise(resolve => this.addEventListener('open', resolve));
        }

        onOpen(f) {
            this.addEventListener('open', f);
        }

        onClose(f) {
            this.addEventListener('close', f);
        }

        onMessage(f) {
            this.addEventListener('message', function (event) {
                let data;
                try {
                    data = JSON.parse(event.data);
                } catch (err) {
                    console.log(event.data);
                    console.error('接收的数据不是Json格式');
                }
                f(data, event);
            });
        }

        send(data) {
            switch (this.state) {
                case 'not-connected':
                    return false;
                case 'disconnected':
                    return false;
            }
            this.ws.send(data);
            return true;
        }

        close() {
            this.ws.close();
        }
    }

    connectWebSocket.MyEvent = class extends Event {
        constructor(event) {
            super(event.type);
            this.data = event.data;
        }
    }
    //---------------收发送数据格式类-----------------
    const Message = class {
        name;
        content;
        type;

        constructor(name, content) {
            this.name = name;
            this.content = content;
        }

        toString() {
            return JSON.stringify(this);
        }
    }

//----------------界面控制类-----------------------
    class ChatBox {
        state;

        constructor() {
            this.frameId = this.init();
            this.ws = new connectWebSocket('wss://echo.websocket.org');
        }

        //iframe加载完成调用
        initSuccess(body) {
            this.state = 'open';
            this.body = body.find('#chatContent');
            this.input = body.find('#xsr input');
            this.button = body.find('#xsr button');
            this.button.click(() => {
                let val = this.input.val();
                if (val.length < 1) return this.layer.msg('输入为空', function () {
                });
                this.sendMessage(val);
                this.input.val('');
            });
            this.ws.connected();
            this.ws.onOpen(() => {
                this.layer.msg('ws连接成功！');
                layer.title('连接成功', this.frameId);
                this.addNotice(new Message(null, 'ws连接成功！'));
            });
            this.ws.onClose(() => {
                if (this.state === 'close') {
                    return
                }
                this.layer.msg('ws链接已断开！');
                this.addNotice(new Message(null, 'ws链接已断开！'));
                layer.title('链接已断开', this.frameId);
            });
            this.ws.onMessage((data) => {
                this.addChatMessage(data);
            })
        }

        sendMessage(text) {
            const news = new Message('自己', text);
            this.addChatMessage(news, true);
            this.ws.send(news);
        }

        addView(jqElem) {
            if (this.state !== 'open') return;
            this.body.append(jqElem);
            setTimeout(() => {
                this.frameWindow.scroll({top: this.body.height(), left: 0, behavior: 'smooth'});
            }, 50);
        }

        addNotice(news = {}) {
            const notice = ChatBox.Notice.clone();
            notice.find('span').text(news.content);
            this.addView(notice);
        }

        addChatMessage(news, b) {
            const t = b ? 'Right' : 'Left';
            const notice = ChatBox[t].clone();
            notice.find('div:eq(1)').text(news.name || '未知用户');
            notice.find('img').attr('src', news.icon);
            notice.find('span').text(news.content);//.css('word-break','break-all');
            this.addView(notice);
        }

        close() {
            this.state = 'close';
            this.ws.close();
        }

        init() {
            //多窗口模式，层叠置顶
            return layer.open({
                type: 2 //此处以iframe举例
                , title: '连接中...'
                , area: ['390px', '630px']
                , shade: 0
                , offset: [ //为了演示，随机坐标
                    0
                    , Math.random() * ($(window).width() - 390)
                ]
                , maxmin: true
                , content: 'chat.html'
                , end: () => {
                    this.close();
                }
                , zIndex: layer.zIndex //重点1
                , success: (layero, index) => {
                    layer.setTop(layero); //重点2
                    this.frameWindow = layero.find('iframe')[0].contentWindow
                    this.frameLayer = new Promise((resolve) => this.frameWindow.layui.use('layer', resolve));
                    this.frameLayer.then((l) => this.layer = l);
                    const body = layer.getChildFrame('body', index);
                    this.initSuccess(body);
                }
            });
        }
    }

    ChatBox.Notice = $('<div class="chat-notice">\n' +
        '    <span>系统消息</span>\n' +
        '  </div>');
    ChatBox.Right = $('<div class="chat-receiver">\n' +
        '    <div><img src="icon/default.png"></div>\n' +
        '    <div>好人·马克思</div>\n' +
        '    <div>\n' +
        '      <div class="chat-right_triangle"></div>\n' +
        '      <span> 最后但并非最不重要的是</span>\n' +
        '    </div>\n' +
        '  </div>');
    ChatBox.Left = $('<div class="chat-sender">\n' +
        '    <div><img src="icon/default.png"></div>\n' +
        '    <div>麦克</div>\n' +
        '    <div>\n' +
        '      <div class="chat-left_triangle"></div>\n' +
        '      <span> 你可以用ionRefresher指令实现拉动刷新，并可以用ionInfiniteScroll指令实现无限滚动。</span>\n' +
        '    </div>\n' +
        '  </div>')
    window.ChatBox = ChatBox;
})